
#include <cstdio>
#include <BPainter>
#include <BMouseEvent>

#include "CrossLineItem.h"

CrossLineItem::CrossLineItem(BGraphicItem* parent) : BGraphicItem(parent)
{
	_hoverIndex = -1;
	_selectIndex = -1;
	_pressed = false;
	_dirty = false;
}
CrossLineItem::~CrossLineItem()
{

}

void CrossLineItem::paint(BPainter& painter)
{
	BGraphicItem::paint(painter);
	if (_linePoints.size())
	{
		painter.setColor(Color_Wire);
		painter.setLineSmooth(true);
		painter.drawLines(_linePoints);

		if (_linePoints.check(_hoverIndex))
		{
			if (_pressed)
				painter.setColor(200, 0, 200);
			else
				painter.setColor(250, 0, 250);
			painter.setPointSmooth(true);
			painter.setPointSize(3);
			painter.drawPoint(_linePoints(_hoverIndex));
		}
		if (_selectIndex != _hoverIndex && _linePoints.check(_selectIndex))
		{
			painter.setColor(100, 150, 200);
			painter.setPointSmooth(true);
			painter.setPointSize(3);
			painter.drawPoint(_linePoints(_selectIndex));
		}
		if (this->hovered() && _linePoints.size() % 2)
		{
			painter.setColor(200, 150, 100);
			painter.setLineStipple(0xf0f0);
			painter.drawLine(_linePoints.last(), _currentPos);
			painter.setLineStipple(0x0000);
		}
		painter.setColor(100, 100, 200);
		painter.setPointSmooth(true);
		painter.setPointSize(4);
		painter.drawPoints(_crossPoints);
	}
}

void CrossLineItem::freshEvent(const BEvent& event)
{
	if (_dirty)
	{
		_crossPoints.reset();
		for (int i = 0; i < _linePoints.size(); i += 2)
		{
			BLine2f line(_linePoints[i], _linePoints[i + 1]);
			int end = i + 2;
			while (end < _linePoints.size())
			{
				BLine2f after(_linePoints[end], _linePoints[end + 1]);
				BPointf point;
				if (line.intersect(after, point))
					_crossPoints.append(point);
				end += 2;
			}
		}
		_dirty = false;
	}
	BGraphicItem::freshEvent(event);
}

void CrossLineItem::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	_currentPos = mouseEvent.pos();
	if (_hoverIndex >= 0)
	{
		_hoverIndex = -1;
		this->fresh();
	}
	BGraphicItem::mouseEnterEvent(mouseEvent);
}
void CrossLineItem::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	if (_hoverIndex >= 0)
	{
		_hoverIndex = -1;
		this->fresh();
	}
	BGraphicItem::mouseLeaveEvent(mouseEvent);
}
void CrossLineItem::mousePressEvent(const BMouseEvent& mouseEvent)
{
	if (_linePoints.check(_hoverIndex))
	{
		_pressed = true;
		this->fresh();
	}
	if (_selectIndex != _hoverIndex)
	{
		_selectIndex = _hoverIndex;
		this->fresh();
	}
	BGraphicItem::mousePressEvent(mouseEvent);
}
void CrossLineItem::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	if (_pressed)
	{
		_pressed = false;
		this->fresh();
	}
	BGraphicItem::mousePressEvent(mouseEvent);
}
void CrossLineItem::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	const BPoint& pos = mouseEvent.pos();
	int hoverIndex = -1;
	for (int i = 0; i < _linePoints.size(); i++)
	{
		int len = (pos - _linePoints[i]).length();
		if (len < 6)
		{
			hoverIndex = i;
			break;
		}
	}
	if (_hoverIndex != hoverIndex)
	{
		_hoverIndex = hoverIndex;
		this->fresh();
	}
	if (_linePoints.size() % 2)
	{
		_currentPos = mouseEvent.pos();
		this->fresh();
	}
	BGraphicItem::mouseMoveEvent(mouseEvent);
}

void CrossLineItem::mouseDoubleClickEvent(const BMouseEvent& mouseEvent)
{
	const BPoint& pos = mouseEvent.pos();
	_linePoints.append(pos);
	_dirty = true;
	this->fresh();
}
